/*
PearReview - The peer review assistant.
Copyright (C) 2009  Dimitrij Pankratz, Anton Musichin
http://www.pearreview.com, info@pearreview.com

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

package com.pearreview.moderatorplugin;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Formatter;
import java.util.HashMap;
import java.util.Map;

import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import com.pearreview.application.Messages;
import com.pearreview.util.pdf.PChunk;
import com.pearreview.util.pdf.PParagraph;
import com.pearreview.util.pdf.PdfPageEventOld;
import com.pearreview.util.review.Aspect;
import com.pearreview.util.review.Attendee;
import com.pearreview.util.review.AttendeeRole;
import com.pearreview.util.review.Meeting;
import com.pearreview.util.review.Review;

public class PDFInvitationDocumentCreator extends AbstractInvitationCreator 
		implements InvitationDocumentCreator {
	private static final long serialVersionUID = 8617887373061474512L;
	
	public static final String PDF_EXTENSION = ".pdf";
	
	private boolean attachFiles;
	private String imagePath;
	private ArrayList<PdfAttachment> attachments = 
		new ArrayList<PdfAttachment>();

	public PDFInvitationDocumentCreator() {
		this(false);
	}
	
	public PDFInvitationDocumentCreator(boolean attachFiles, File imageFile) {
		this(false);
		if(imageFile != null)
			this.imagePath = imageFile.getAbsolutePath();
		this.attachFiles = attachFiles;
	}
	
	public PDFInvitationDocumentCreator(boolean attachFiles) {
		this.attachFiles = attachFiles;
	}
	
	@Override
	public void create(Review review, java.util.List<Meeting> meetings, 
			Attendee attendee, OutputStream outputStream) 
			throws IOException, DocumentException {
		
		attachments = new ArrayList<PdfAttachment>();
		
		//padding left, right, top, bottom = 50, 50, 50, 50
		Document doc = new Document(PageSize.A4, 50, 50, 50, 50);
		
		PdfWriter writer = PdfWriter.getInstance(doc, outputStream);
		//writer.setViewerPreferences(PdfWriter.FitWindow);
		PdfDestination dest = new PdfDestination(PdfDestination.FIT);
		writer.setViewerPreferences(PdfWriter.CenterWindow);
		
		String reviewName = (isEmpty(review.getName()))?
				getEmptyField():
				review.getName();
				
		writer.setPageEvent(new PdfPageEventOld(Messages.getString(
				"PearReview.invitation.invitation_to_review") + " - " + 
				reviewName));

		
		doc.open();
		
		new PdfOutline(writer.getDirectContent().getRootOutline(), dest, 
				Messages.getString("PearReview.invitation.invitation"));
		
		
		// TODO
		if(attachFiles && review.getProduct() != null) {
			attachFiles(writer, review.getProduct().getReference());
			writer.setViewerPreferences(PdfWriter.PageModeUseAttachments);
		}
		
		//add image
		if (this.imagePath != null)
			this.writeLogo(doc, this.imagePath);
		
		//add heading
		this.createMainText(doc, Messages.getString(
				"PearReview.invitation.invitation_to_review"));
		
		PdfContentByte cb = writer.getDirectContent();
		cb.setColorStroke(new GrayColor(0.2f));
		cb.setColorFill(new GrayColor(0.9f));
		cb.moveTo(50, 710);
		cb.lineTo(545, 710);
		cb.closePathFillStroke();
		
		//add recipient
		this.writeRecipient(attendee, doc);
		
		
		//add purpose
		this.createReasonText(doc, attendee, Messages.getString(
			"PearReview.invitation.invitation_text"));
		
		//add review info
		this.writeReviewInformation(review, attendee, doc);
		
		//add product info
		this.createProductText(review, doc);
		
		// TODO meetings
		if(meetings != null) {
			for(int i = 0 ; i < meetings.size() ; i++) {
				this.writeMeetingInformation(meetings.get(i), doc);
			}
		}
		
		//add aspects
		if (attendee.getRole() == AttendeeRole.Reviewer)
			this.createAspectsList(attendee, doc, 
					Messages.getString("PearReview.invitation.your_aspects"));
			
		doc.close();
		writer.close();
	}
	
	@Override
	public String getFileExtension() {
		return PDF_EXTENSION;
	}
	
	private byte[] getBytesFromFile(File file) throws IOException {
		InputStream is = new FileInputStream(file);
		long length = file.length();
		byte[] bytes = new byte[(int) length];
		int offset = 0;
		int numRead = 0;
		while (offset < bytes.length
				&& (numRead = is.read(bytes, 
						offset, bytes.length - offset)) >= 0) {
			offset += numRead;
		}
		if (offset < bytes.length) {
			throw new IOException("Could not completely read file "
					+ file.getName());
		}
		is.close();
		return bytes;
	}
	
	protected void attachFiles(PdfWriter writer, java.util.List<String> lst) 
			throws IOException {
		/* API doc
		 * 
		public void PdfWriter::addFileAttachment(String description,
                byte[] fileStore,
                String file,
                String fileDisplay)
         throws IOException
         */
		java.util.List<String> fileList = getFileList(lst);
		
		if(fileList == null)
			return;
		
		for(String ref: fileList) {
			File file = getFile(ref);
			
			/*
			writer.addFileAttachment(file.toString(), 
					null, 
					file.toString(), 
					file.getName());
					
					*/
			
			String fileString = file.getName();
			
			PdfAnnotation attachment = PdfAnnotation.createFileAttachment(
					writer, new Rectangle(100f, 650f, 150f, 700f),
					fileString + " (" + Messages.getString(
							"PearReview.invitation.attachment") + ")",
					getBytesFromFile(file),
					null, fileString);
			
			PdfAttachment att = new PdfAttachment();
			att.setAnnotation(attachment);
			att.setFileName(fileString);
			
			attachments.add(att);
		}
	}
	
	/**
	 * 
	 * @param doc
	 * @param logoFile
	 * @throws MalformedURLException
	 * @throws IOException
	 * @throws DocumentException
	 */
	private void writeLogo(Document doc, String logoFile) 
			throws MalformedURLException, IOException, DocumentException {
	
		Image img = Image.getInstance(logoFile);
		img.scaleToFit(70, 70);
		img.setAlignment(Image.RIGHT | Image.TEXTWRAP);
		doc.add(img);
	}
	

	/**
	 * 
	 * @param attendee
	 * @param doc
	 * @throws DocumentException
	 * @throws IOException
	 */
	private void writeRecipient(Attendee attendee, Document doc) 
		throws DocumentException, IOException {
		
		PParagraph pTo = new PParagraph(
				Messages.getString("PearReview.invitation.to"));
		Font font = pTo.getFont();
		font.setStyle(Font.BOLD);
			
		PParagraph pName = (isEmpty(attendee.getName()))?
				new PParagraph(getEmptyFieldPChunk()):
				new PParagraph(attendee.getName());
		font = pName.getFont();
		font.setSize(12);
		font.setStyle(Font.BOLD);
		
		PParagraph pContact = (isEmpty(attendee.getContact()))?
				new PParagraph(getEmptyFieldPChunk()):
				new PParagraph(attendee.getContact());
		font = pContact.getFont();
		font.setSize(12);
		font.setStyle(Font.BOLD);
		
		pTo.setSpacingBefore(50f);
		pTo.setSpacingAfter(10f);
		pContact.setSpacingAfter(40f);
		
		doc.add(pTo);
		doc.add(pName);
		doc.add(pContact);
	}
	
	/**
	 * 
	 * @param attendee
	 * @param doc
	 * @param text
	 * @throws DocumentException
	 */
	private void createAspectsList(Attendee attendee, Document doc, 
			String text) throws DocumentException {

		PChunk cHeading = new PChunk(text);
		Font font = cHeading.getFont();
		font.setStyle(Font.BOLD);
		font.setColor(new BaseColor(0x333333));
		font.setSize(16);
		
		PParagraph pHeading = new PParagraph();
		pHeading.setSpacingAfter(20);
		pHeading.add(cHeading);
		
		doc.add(pHeading);
		
		Map<String, ArrayList<Aspect>> categories = 
			new HashMap<String, ArrayList<Aspect>>();
		
		
		if(attendee.getAspects() != null)
		for (Aspect aspect: attendee.getAspects()) {
			if (categories.containsKey(aspect.getCategory())) {
				ArrayList<Aspect> list = categories.get(aspect.getCategory());
				list.add(aspect);
			} else {
				ArrayList<Aspect> list = new ArrayList<Aspect>();
				list.add(aspect);
				categories.put(aspect.getCategory(), list);
			}
		}
		
		//create the table and table heading
		PdfPTable table = new PdfPTable(2);
		float[] widths = { 1f, 3f};
		table.setWidths(widths);
		table.setWidthPercentage(100);
		table.setHeaderRows(1);
		PdfPCell h1 = new PdfPCell(new PParagraph(Messages.getString(
				"PearReview.invitation.category")));
		h1.setGrayFill(0.7f);
		h1.setPaddingBottom(4);
		h1.setPaddingTop(4);
		table.addCell(h1);
		
		PdfPTable nestedHead = new PdfPTable(2);
		float[] widthsNestedHead = { 1f, 2f};
		nestedHead.setWidths(widthsNestedHead);
		
		PdfPCell h2 = new PdfPCell(new PParagraph(Messages.getString(
				"PearReview.invitation.directive")));
		h2.setGrayFill(0.7f);
		h2.setPaddingBottom(4);
		h2.setPaddingTop(4);
		nestedHead.addCell(h2);
		PdfPCell h3 = new PdfPCell(new PParagraph(Messages.getString(
				"PearReview.invitation.description")));
		h3.setGrayFill(0.7f);
		h3.setPaddingBottom(4);
		h3.setPaddingTop(4);
		nestedHead.addCell(h3);
		
		PdfPCell h4 = new PdfPCell(nestedHead);
		table.addCell(h4);
		
		PdfPCell cell;
		
		//write the content of the table
		int row = 0;
		for (String key: categories.keySet()) {
			
			ArrayList<Aspect> list = categories.get(key);
			
			//add category
			cell = new PdfPCell(new PParagraph(key));
			//if (gray)
			//cell.setGrayFill(0.9f);
			table.addCell(cell);
			
			//add directives
			PdfPTable nested = new PdfPTable(2);
			float[] widthsNested = { 1f, 2f};
			nested.setWidths(widthsNested);
			
			for (int i=0; i<list.size(); i++) {
				boolean gray = false;
				if (row % 2 == 1) {
					gray = true;
				}
				cell = new PdfPCell(new PParagraph(list.get(i)
						.getDirective()));
				if (gray)
					cell.setGrayFill(0.9f);
				nested.addCell(cell);
				
				cell = new PdfPCell(new PParagraph(list.get(i)
						.getDescription()));
				if (gray)
					cell.setGrayFill(0.9f);
				nested.addCell(cell);
				row++;
			}
			table.addCell(new PdfPCell(nested));
		}

		
		doc.add(table);
	}
	
	private void createMainText(Document doc, String text) 
			throws DocumentException {

		PChunk cHeading = new PChunk(text);
		Font font = cHeading.getFont();
		font.setStyle(Font.BOLD);
		font.setSize(20f);
		cHeading.setFont(font);
		
		PParagraph pHeading = new PParagraph();
		//pHeading.setAlignment(Element.ALIGN_CENTER);
		pHeading.add(cHeading);
		pHeading.setSpacingAfter(30f);
		
		PParagraph pSpace = new PParagraph(" ");
		pSpace.setSpacingAfter(10f);
		
		doc.add(pSpace);
		doc.add(pHeading);
	
	}
	
	private void createReasonText(Document doc, Attendee attendee, String text) 
			throws DocumentException {
		
		String role = "";
		if (!(attendee.getRole() == null)) {
			
			switch (attendee.getRole()) {
			case Moderator:
				role = Messages.getString("PearReview.review.modarator");
				break;
			
			case Scribe:
				role = Messages.getString("PearReview.review.scribe");
				break;
				
			case Reviewer:
				role = Messages.getString("PearReview.review.reviewer");
				break;
				
			case Author:
				role = Messages.getString("PearReview.review.author");
				break;
				
			case Customer:
				role = Messages.getString("PearReview.review.customer");
				break;
			}
		}
	
		Formatter formatter = new Formatter();
		text = formatter.format(text, role).toString();
		
		PParagraph pHeading = new PParagraph(text);
		
		PParagraph pSpace = new PParagraph(" ");
		pSpace.setSpacingAfter(20f);
		
		doc.add(pHeading);
		doc.add(pSpace);
	
	}
	
	/**
	 * 
	 * @param review
	 * @param doc
	 * @throws DocumentException
	 */
	private void createProductText(Review review, Document doc) 
			throws DocumentException {
		PChunk cHeading = new PChunk(Messages.getString(
				"PearReview.invitation.product_information"));
		Font font = cHeading.getFont();
		font.setStyle(Font.BOLD);
		font.setColor(new BaseColor(0x333333));
		font.setSize(16);
		
		PParagraph pHeading = new PParagraph();
		pHeading.setSpacingAfter(20);
		pHeading.add(cHeading);
		
		doc.add(pHeading);
		
		PdfPTable table = new PdfPTable(2);
		float[] widths = { 1f, 3f};
		table.setWidths(widths);
		table.setWidthPercentage(100);
		
		//add product name
		PChunk caption = new PChunk(Messages.getString(
				"PearReview.Moderator.review.name_2") + ": ");
		font = caption.getFont();
		font.setStyle(Font.BOLD);
		font.setColor(new BaseColor(0x000000));
		
		PChunk content = (isEmpty(review.getProduct().getName()))?
				getEmptyFieldPChunk():
				new PChunk(review.getProduct().getName());
		
		PdfPCell cell = new PdfPCell(new PParagraph(caption));
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
				
		cell = new PdfPCell(new PParagraph(content));
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
		
		//add product version
		caption = new PChunk(Messages.getString(
				"PearReview.invitation.version") + ": ");
		font = caption.getFont();
		font.setColor(new BaseColor(0x000000));
		font.setStyle(Font.BOLD);
		
		content = (isEmpty(review.getProduct().getVersion()))?
				getEmptyFieldPChunk():
				new PChunk(review.getProduct().getVersion());
		
		cell = new PdfPCell(new PParagraph(caption));
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
				
		cell = new PdfPCell(new PParagraph(content));
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
		
		
		//add product references
		//ArrayList<File> fileRef = new ArrayList<File>();
		ArrayList<String> stringRef = new ArrayList<String>();
		
		if(review.getProduct().getReference() != null) {
			for(String ref: review.getProduct().getReference()) {
				File file = getFile(ref);
				if (file == null) {
					//fileRef.add(file);
					stringRef.add(ref);
				}
			}
		}
		
		
		caption = new PChunk(Messages.getString(
				"PearReview.invitation.references") + ": ");
		font = caption.getFont();
		font.setStyle(Font.BOLD);
		font.setColor(new BaseColor(0x000000));
		cell = new PdfPCell(new PParagraph(caption));
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
		
		cell = new PdfPCell(new PParagraph());
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
		
		
		PParagraph cList = new PParagraph();
		
		for (String ref: stringRef) {
			cList.add(ref);
			cList.add("\n");
		}
		
		PParagraph pCap = new PParagraph(Messages.getString(
				"PearReview.invitation.text_references"));
		cell = new PdfPCell(pCap);
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
		
		PParagraph p = new PParagraph();
		
		if (stringRef.size() > 0) {
			p.add(cList);
		} else {
			p.add(getEmptyFieldPChunk());
		}

		cell = new PdfPCell(p);
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
		
		
		cList = new PParagraph();
		
		/*
		for (File ref: fileRef) {
			cList.add(ref.getName());
			cList.add("\n");
		}
		*/
		for (PdfAttachment ref: attachments) {
			cList.add(new PChunk("   ").setAnnotation(ref.getAnnotation()));
			cList.add(new PChunk("  "));
			cList.add(new PChunk(ref.getFileName()));
			cList.add("\n");
		}
		
		
		pCap = new PParagraph(Messages.getString(
			"PearReview.invitation.file_references"));
		cell = new PdfPCell(pCap);
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
		
		p = new PParagraph();
		
		if (attachments.size() > 0) {
			p.add(cList);
		} else {
			p.add(getEmptyFieldPChunk());
		}
		
		cell = new PdfPCell(p);
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
	
		doc.add(table);
		
		PParagraph pLast = new PParagraph();
		pLast.setSpacingAfter(40f);

		doc.add(pLast);
	}

	private void writeReviewInformation(Review review, Attendee attendee,
			Document doc) throws DocumentException {
		PChunk cHeading = new PChunk(Messages.getString(
		"PearReview.invitation.review_information"));
		Font font = cHeading.getFont();
		font.setColor(new BaseColor(0x333333));
		font.setStyle(Font.BOLD);
		font.setSize(16);
		
		PParagraph pHeading = new PParagraph();
		pHeading.setSpacingAfter(20);
		pHeading.add(cHeading);
		
		doc.add(pHeading);
		
		PdfPTable table = new PdfPTable(2);
		float[] widths = { 1f, 3f};
		table.setWidths(widths);
		table.setWidthPercentage(100);
		
		//add review name
		PChunk caption = new PChunk(Messages.getString(
				"PearReview.Moderator.review.name_2") + ": ");
		font = caption.getFont();
		font.setColor(new BaseColor(0x000000));
		font.setStyle(Font.BOLD);
		
		PChunk content = (isEmpty(review.getName()))?
				getEmptyFieldPChunk():
				new PChunk(review.getName());
		
		PdfPCell cell = new PdfPCell(new PParagraph(caption));
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
		
		cell = new PdfPCell(new PParagraph(content));
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
		
		//add review description
		caption = new PChunk(Messages.getString(
				"PearReview.Moderator.review.description") + ": ");
		font = caption.getFont();
		font.setColor(new BaseColor(0x000000));
		font.setStyle(Font.BOLD);
		
		content = (isEmpty(review.getDescription()))?
				getEmptyFieldPChunk():
				new PChunk(review.getDescription());
		
		cell = new PdfPCell(new PParagraph(caption));
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
		
		cell = new PdfPCell(new PParagraph(content));
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
		
		//add review comments
		caption = new PChunk(Messages.getString(
				"PearReview.Moderator.review.comments") + ": ");
		font = caption.getFont();
		font.setColor(new BaseColor(0x000000));
		font.setStyle(Font.BOLD);
		
		content = (isEmpty(review.getComments()))?
				getEmptyFieldPChunk():
				new PChunk(review.getComments());
		
		cell = new PdfPCell(new PParagraph(caption));
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
				
		cell = new PdfPCell(new PParagraph(content));
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
		
		//add review attendee role
		if (!(attendee.getRole() == null)) {
			String role = "";
			
			switch (attendee.getRole()) {
			case Moderator:
				role = Messages.getString("PearReview.review.modarator");
				break;
			
			case Scribe:
				role = Messages.getString("PearReview.review.scribe");
				break;
				
			case Reviewer:
				role = Messages.getString("PearReview.review.reviewer");
				break;
				
			case Author:
				role = Messages.getString("PearReview.review.author");
				break;
				
			case Customer:
				role = Messages.getString("PearReview.review.customer");
				break;
			}
			
			caption = new PChunk(Messages.getString(
					"PearReview.invitation.your_role"));
			font = caption.getFont();
			font.setColor(new BaseColor(0x000000));
			font.setStyle(Font.BOLD);
			
			content = new PChunk(role);
			
			cell = new PdfPCell(new PParagraph(caption));
			cell.setBorder(Rectangle.NO_BORDER);
			table.addCell(cell);
					
			cell = new PdfPCell(new PParagraph(content));
			cell.setBorder(Rectangle.NO_BORDER);
			table.addCell(cell);
		}
		
		doc.add(table);
		
		PParagraph pLast = new PParagraph();
		pLast.setSpacingAfter(40f);

		doc.add(pLast);
	}
	
	
	/**
	 * Create and add meeting information.
	 * 
	 * @param meeting
	 * @param doc
	 * @throws DocumentException
	 */
	private void writeMeetingInformation(Meeting meeting, Document doc) 
			throws DocumentException {
		
		PChunk cHeading = new PChunk(Messages.getString(
				"PearReview.invitation.review_meeting"));
		Font font = cHeading.getFont();
		font.setColor(new BaseColor(0x333333));
		font.setStyle(Font.BOLD);
		font.setSize(16);
		
		PParagraph pHeading = new PParagraph();
		pHeading.setSpacingAfter(10);
		pHeading.add(cHeading);
		
		doc.add(pHeading);
		
		PdfPTable table = new PdfPTable(2);
		float[] widths = { 1f, 3f};
		table.setWidths(widths);
		table.setWidthPercentage(100);
		
		//add meeting location
		PChunk caption = new PChunk(Messages.getString(
				"PearReview.Moderator.meetings.place") + ": ");
		font = caption.getFont();
		font.setColor(new BaseColor(0x000000));
		font.setStyle(Font.BOLD);
		PdfPCell cell = new PdfPCell(new PParagraph(caption));
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
		
		PChunk content = (isEmpty(meeting.getPlannedLocation()))?
				getEmptyFieldPChunk():
				new PChunk(meeting.getPlannedLocation());
		cell = new PdfPCell(new PParagraph(content));
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
		
		
		//add meeting date
		caption = new PChunk(Messages.getString(
				"PearReview.Moderator.meetings.date") + ": ");
		font = caption.getFont();
		font.setColor(new BaseColor(0x000000));
		font.setStyle(Font.BOLD);
		
		content = (meeting.getPlannedDate()==null)?
				getEmptyFieldPChunk():
				new PChunk(DateFormat.getDateInstance().format(
				meeting.getPlannedDate().getTime()));
		
		cell = new PdfPCell(new PParagraph(caption));
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
		
		cell = new PdfPCell(new PParagraph(content));
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
		
		
		//add meeting start
		caption = new PChunk(Messages.getString(
				"PearReview.Moderator.meetings.start") + ": ");
		font = caption.getFont();
		font.setColor(new BaseColor(0x000000));
		font.setStyle(Font.BOLD);
		
		content = (meeting.getPlannedStart() == null)?
				getEmptyFieldPChunk():
				new PChunk(DateFormat.getTimeInstance(
				DateFormat.SHORT).format(
						meeting.getPlannedStart().getTime()));
		
		cell = new PdfPCell(new PParagraph(caption));
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
		
		cell = new PdfPCell(new PParagraph(content));
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
		
		
		//add meeting end
		caption = new PChunk(Messages.getString(
				"PearReview.Moderator.meetings.end") + ": ");
		font = caption.getFont();
		font.setColor(new BaseColor(0x000000));
		font.setStyle(Font.BOLD);
		
		content = (meeting.getPlannedEnd() == null)?
				getEmptyFieldPChunk():
				new PChunk(DateFormat.getTimeInstance(
				DateFormat.SHORT)
				.format(meeting.getPlannedEnd().getTime()));
		
		cell = new PdfPCell(new PParagraph(caption));
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
		
		cell = new PdfPCell(new PParagraph(content));
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
		
		
		//add meeting comments
		caption = new PChunk(Messages.getString(
				"PearReview.Moderator.meetings.comments") + ": ");
		font = caption.getFont();
		font.setColor(new BaseColor(0x000000));
		font.setStyle(Font.BOLD);
		
		content = (isEmpty(meeting.getComments()))?
				getEmptyFieldPChunk():
				new PChunk(meeting.getComments());
		
		cell = new PdfPCell(new PParagraph(caption));
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
		
		cell = new PdfPCell(new PParagraph(content));
		cell.setBorder(Rectangle.NO_BORDER);
		table.addCell(cell);
		
		
		doc.add(table);
		
		PParagraph pLast = new PParagraph();
		pLast.setSpacingAfter(40f);

		doc.add(pLast);
	}
	
	private String getEmptyField() {
		return Messages.getString("PearReview.protocol.empty");
	}
	
	private PChunk getEmptyFieldPChunk() {
		PChunk c = new PChunk(getEmptyField());
		Font f = c.getFont();
		f.setStyle(Font.ITALIC);
		
		return c;
	}
	
	private boolean isEmpty(String str) {
		if (!(str == null || str.equals(""))) {
			return false;
		} else {
			return true;
		}
	}
	
	private class PdfAttachment {
		private PdfAnnotation annotation;
		private String fileName;
		
		public PdfAnnotation getAnnotation() {
			return annotation;
		}
		public void setAnnotation(PdfAnnotation annotation) {
			this.annotation = annotation;
		}
		public String getFileName() {
			return fileName;
		}
		public void setFileName(String fileName) {
			this.fileName = fileName;
		}
	}
}